<template>
  <div style="height: 60px">
    <createHeader :isBorder="true" :isBack="true" @isback="FnBack">
      添加节点
    </createHeader>
  </div>
  <div style="height: calc(100% - 60px)">
    <el-card>
      <el-form :model="formData" ref="formRef" label-width="auto" label-position="left">
        <el-form-item label="节点区域" prop="region_id" required :rules="{validator: region_validate, trigger: ['blur', 'change']}">
          <el-select
            placeholder="请选择节点区域"
            v-model="formData.region_id"
            @change="fnAzChange">
            <el-option v-for="(item, index) in regionList" :key="index" :label="item.region_name" :value="item.region_id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="集群" prop="cluster_id" required :rules="{validator: cluster_validate, trigger: ['blur', 'change']}">
          <el-select
            placeholder="请选择集群"
            v-model="formData.cluster_id"
            @change="fnClusterChange">
            <el-option v-for="(item, index) in clusterList" :key="index" :label="item.cluster_name" :value="item.cluster_id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="节点类型">
          <el-radio-group v-model="formData.node_type">
            <el-radio-button label="worker">Worker</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="节点来源">
          <el-radio-group v-model="formData.node_source">
            <el-radio-button label="source_pond">资源池</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="计算类型和规格">
          <div class="out-box">
            <div class="inner-box">
              <el-table :data="specTable" @selection-change="handleSelectionChange">
                <el-table-column type="selection" width="55" />
                <el-table-column prop="host_name" label="主机名" min-width="150"></el-table-column>
                <el-table-column label="节点区域" min-width="120">
                  <template #default="scope">
                    {{ cur_region_name }}
                  </template>
                </el-table-column>
                <el-table-column label="集群" min-width="120">
                  <template  #default="scope">
                    {{ cur_cluster_name }}
                  </template>
                </el-table-column>
                <el-table-column prop="cpu_model" label="CPU" min-width="120"></el-table-column>
                <el-table-column label="内存" min-width="120">
                  <template #default="scope">
                    {{ scope.row.ram_size>=0 ? scope.row.ram_size : '-' }}G
                  </template>
                </el-table-column>
                <el-table-column prop="gpu_name" label="扩展配置" min-width="120"></el-table-column>
                <el-table-column prop="status" label="设备状态" min-width="120"></el-table-column>
              </el-table>
            </div>
          </div>
          <span v-if="tip_str" class="tip_str" v-html="tip_str"></span>
        </el-form-item>
        <el-form-item label="执行命令" prop="shell">
          <div class="position-relative">
            <div class="file-btn c_btn">
              <div class="text">导入shell脚本</div>
              <input type="file" :id="'file_btn'" accept=".sh" title="">
            </div>
          </div>
          <el-input class="m-t-50" type="textarea" v-model="formData.shell" :rows="5"></el-input>
        </el-form-item>
        <div class="display-flex">
          <div class="fake-form-label">节点标签</div>
          <div>
            <div>
              <el-button type="text" @click="fnAdd()" :disabled="addDisabled">+添加</el-button>
              <span>最多可新创建5个标签</span>
            </div>
            <template v-for="(item, index) in keyValueList" :key="index">
              <div class="display-flex align-top" :ref="el => { if (el) keyValueRefs[index] = el }">
                <div class="form-item-inline">
                  <el-form-item
                    :prop="'key'+index"
                    :rules="[
                      {validator: (rule, value, callback) => keyValidator(rule, value, callback, index), trigger: ['blur', 'change', 'input']}
                    ]">
                    <template #label>
                      <div class="display-flex align-center">
                        <div>键</div>
                        <span class="required m-l-2">*</span>
                        <el-tooltip
                          effect="light"
                          placement="top">
                          <template #default>
                            <i class="el-icon-question"></i>
                          </template>
                          <template #content>
                            1.可以有两段：前缀(可选)和名称 (必须)，用/分隔;<br>
                            2.前缀必须是DNS格式，由.分隔，不超过253个字符，后跟/;<br>
                            3.名称以数字或字母开头和结尾，中间可以是"."、"_"、"-";<br>
                            4.名称长度不超过63个字符。
                          </template>
                        </el-tooltip>
                      </div>
                    </template>
                    <el-input v-model="item.key" :disabled="index===0 || index===1" class="w-290"></el-input>
                  </el-form-item>
                  <el-form-item
                    :prop="'value'+index"
                    :rules="[
                      {validator: (rule, value, callback) => valueValidator(rule, value, callback, index), trigger: ['blur', 'change', 'input']}
                    ]">
                    <template #label>
                      <div class="display-flex align-center">
                        <div>值</div>
                        <el-tooltip
                          effect="light"
                          placement="top">
                          <template #default>
                            <i class="el-icon-question"></i>
                          </template>
                          <template #content>
                            1.以数字或字母开头和结尾，中间可以是"."、"_"和"-"；<br>
                            2.长度不超过63个字符。
                          </template>
                        </el-tooltip>
                      </div>
                    </template>
                    <el-input v-model="item.value" :disabled="index===0 || index===1" class="w-29 0"></el-input>
                  </el-form-item>
                  <div class="m-l-20" v-if="index!==0 && index!==1">
                      <i class="el-icon-remove pointer" style="font-size: 16px; color:#EB2A2A" @click="fnDelete(index)"></i>
                  </div>
                </div>
              </div>
            </template>
          </div>
        </div>
      </el-form>
      <div class="footer">
        <el-button type="primary" @click="fnConfirm">确认</el-button>
      </div>
    </el-card>
    
  </div>
</template>
<script setup>
import { computed, onMounted, reactive, ref, nextTick } from 'vue';
import createHeader from '@/components/createHeader.vue';
import edgeService from '@/service/eks/edge.js';
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
import {labelToKeyValue} from '@/utils/console.js'

const regionList = ref([])
const clusterList = ref([])
const keyValueRefs = ref([]);
const router = useRouter()
const keyValueList = ref([{
  key: 'katacontainers.io/kata-runtime',
  value: 'true'
}, {
  key: 'node.kubernetes.io/for-eci',
  value: 'node.kubernetes.io-for-eci'
}])
const formData = reactive({
  region_id: '',
  cluster_id: '',
  node_type: 'worker',
  node_source: 'source_pond',
  shell: ''
})
const specTable = ref([])
const FnBack = () => {
  window.history.back()
}
const getRegionList = async () => {
  await edgeService.getRegionList().then((res) => {
    if (res.code === 'Success') {
      regionList.value = res.data ? res.data : [];
    }
  })
}
getRegionList()
const cur_region_name = computed(() => {
  return regionList.value.find(el => el?.region_id === formData.region_id)?.region_name ?? '-'
})
const fnAzChange = () => {
  formData.cluster_id = ''
  getClusterList()
  fnClusterChange()
}
const getClusterList = async () => {
  await edgeService.getEdgeClusters({region_id: formData.region_id}).then((res) => {
    if (res.code === 'Success') {
      clusterList.value = res.data ? res.data : [];
    }
  })
}
const cur_cluster_name = computed(() => {
  return clusterList.value.find(el => el?.cluster_id === formData.cluster_id)?.cluster_name ?? '-'
})
const fnClusterChange = (val) => {
  specTable.value = []
  if(val) {
    getSpecData()
  }
}
// 规格提示
const tip_str = ref('')
const getSpecData = async () => {
  tip_str.value = ''
  await edgeService.getKvmHosts({cluster_id: formData.cluster_id}).then((res) => {
    if (res.code === 'Success') {
      specTable.value = res.data ? res.data : [];
      if(specTable.value && specTable.value.length) {
        tip_str.value = `提示：依据所选节点的cpu类型会给节点打一个特定标签，比如节点${specTable.value[0].host_name}会打上标签<span style="color: #f13a22;"> feature.node.kubernetes.io/cpu-model.vendor_id=${specTable.value[0].cpu_type}</span>`
      }
    }
  })
}
// 选择规格
const specData = ref([])
const handleSelectionChange = (val) => {
  specData.value = [...val]
}
// 导入shell
let file = ref(null)
const FnListener = () => {
  file.value = document.querySelector(`#file_btn`)
  file.value.addEventListener('change', () => {
    let file_reader = new FileReader()
    file_reader.readAsText(file.value.files[0])
    file_reader.onload = (e) => {
      // 给inputArea赋值
      formData.shell = e.target.result
    }
  })
}
// 表单校验
const region_validate = (rule, value, callback) => {
  if (value === '') {
    callback(new Error('请选择节点区域'))
  } else {
    callback()
  }
}
const cluster_validate = (rule, value, callback) => {
  if (value === '') {
    callback(new Error('请选择集群'))
  } else {
    callback()
  }
}

let prefix = ''
let suffix = ''
let ValidIpAddressRegex = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/$/;
let ValidHostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\/$/;
let ValidaName = /^[0-9a-zA-Z][0-9a-zA-Z._-]{0,62}[0-9a-zA-Z]$/;  //名称
let ValidaName_t = /^[0-9a-zA-Z]$/;
const keyValidator = (rule, value, callback, index) => {
  if (keyValueList.value[index].key !== '') {
    let key = keyValueList.value[index].key
    let devide_index = key.indexOf('/');
    prefix = key.slice(0, devide_index + 1);   // 带/的前缀
    suffix = key.slice(devide_index + 1);  // /后的名称
  } else {
    keyValueList.value[index].keyVaildate = false
    callback(new Error("请输入键"))
  }
  if(prefix && (!ValidIpAddressRegex.test(prefix) && !ValidHostnameRegex.test(prefix))) {
    callback(new Error("键格式不正确，请重新输入"))
  } else if (prefix && (ValidIpAddressRegex.test(prefix) || ValidHostnameRegex.test(prefix)) && (prefix.length > 254 || prefix.length < 1)) { // 253,后面带了个/
    callback(new Error("键前缀最大长度为253个字符，请重新输入"))
  } else if(suffix && !ValidaName.test(suffix) && !ValidaName_t.test(suffix)) {
    callback(new Error("键格式不正确，请重新输入"))
  } else if(suffix && (ValidaName.test(suffix) || ValidaName_t.test(suffix)) && (suffix.length > 63 || suffix.length < 1)) {
    callback(new Error("键名称最大长度为63个字符，请重新输入"))
  } else {
    callback()
  }
}
const valueValidator = (rule, value, callback, index) => {
  let curValue = keyValueList.value[index].value
  if(curValue && !ValidaName.test(curValue) && !ValidaName_t.test(curValue)) {
    callback(new Error('值格式不正确，请重新输入'))
  } else if(curValue && (ValidaName.test(curValue) || ValidaName_t.test(curValue)) && (curValue.length > 63 || curValue.length < 1)) {
    callback(new Error('值最大长度为63个字符，请重新输入'))
  } else {
    keyValueList.value[index].valueVaildate = true
    callback()
  }
}
const addDisabled = computed(() => {
  return keyValueList.value.length >= 7 
})
const fnAdd = () => {
  keyValueList.value.push({
    key: '',
    value: ''
  })
  nextTick(() => {
    if (keyValueRefs.value.length > 0) {
      const newIndex = keyValueRefs.value.length - 1;
      const newElement = keyValueRefs.value[newIndex];
      if (newElement) {
        newElement.scrollIntoView({ behavior: 'smooth', block: 'end' });
      }
    }
  });
}
const fnDelete = (index) => {
  keyValueList.value.splice(index, 1)
}
const formRef = ref(null)
const fnConfirm = () => {
  formRef.value.validate((valid) => {
    if(valid) {
      if(specData.value < 1) {
        ElMessage.error('请选择节点规格')
        return
      }
      let keyList = keyValueList.value.map(item => item.key)
      if(keyList.length > new Set(keyList).size) {
        ElMessage.error('标签key不能重复')
        return
      }
      let params = specData.value.map(item => {
        return {
          cluster_id: formData.cluster_id,
          cpu_size: item.cpu_size,
          cpu_model: item.cpu_model,
          ram_size: item.ram_size,
          gpu_sum: item.gpu_sum,
          gpu_name: item.gpu_name,
          host_id: item.host_id,
          host_name: item.host_name,
          shell: formData.shell,
          labels: labelToKeyValue(keyValueList.value),
        }
      })
      edgeService.addEdgeNode(params).then(res => {
        if(res.code === 'Success') {
          ElMessage.success('添加节点任务已下发')
          fnToNodeList()
        }
        if(res.code === 'PartFailed') {
          fnToNodeList()
        }
      })
    }
  })  
}
const fnToNodeList = () => {
  router.push({
    name: 'eks_2_edge_node',
    query: {
      region_id: formData.region_id,
      cluster_id: formData.cluster_id
    }
  })
}
onMounted(() => {
  if(document.querySelector(`#file_btn`)) {
    FnListener()
  }
})
</script>
<style scoped lang="scss">
.out-box {
  height: 300px;
  width: 100%;
  position: relative;
  .inner-box {
    height: 100%;
    width: 100%;
    position: absolute;
    overflow-y: auto;
    :deep(.el-table__body tr.current-row > td) {
      background-color: #fdb598;
    }
  }
}
.file-btn {
  position: absolute;
  top: 6px;
  right: 12px;
  width: 142px;
  height: 28px;
  padding: 0;
  overflow: hidden;
  input {
    position: absolute;
    top: -6px;
    left: 0;
    width: 140px;
    height: 32px;
    margin-top: -4px;
    font-size: 0;
    opacity: 0;
    cursor: pointer;
  }
  .text{
    display: inline-block;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 28px;
    line-height: 26px;
    text-align: center;
  }
}
.c_btn {
  color: #fff;
  background: #455cc6;
}
.fake-form-label {
  line-height: 28px;
  width: 110px;
  text-align: right;
  color: #606266;
  font-size: 14px;
  padding-right: 12px;
  box-sizing: border-box;
}
.required {
  color: #EB2A2A;
}
.form-item-inline {
  :deep(.el-form-item), div  {
    display: inline-block
  }
}
.footer {
  text-align: right;
  margin-top: 10px;
}
.tip_str {
  font-size: 12px;
  color: #383838;
  
}
</style>